<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <script type="text/javascript" src="dbscan.js"></script>
    <style type="text/css">
        td.show { vertical-align: top; padding: 20px }
    </style>
    <body>
        <form>
            <table>
                <caption>data</caption>
                <tr><td><input type="text" name="dataInput" value="ABCDE">
                    <td><input type="text" name="dataInput">
                    <td><input type="text" name="dataInput">
                    <td><input type="text" name="dataInput">
                    <td><input type="text" name="dataInput">
                <tr><td><input type="text" name="dataInput">
                    <td><input type="text" name="dataInput">
                    <td><input type="text" name="dataInput">
                    <td><input type="text" name="dataInput">
                    <td><input type="text" name="dataInput">
            </table>
            <table>
                <tr><td><label>epsilon <input type="text" name="epsilonInput" value=1></label>
                <tr><td><label>minimum points per cluster <input type="text" name="minPtsInput" value=2></label>
                <tr><td><button type="button" onclick="analyze()">analyze</button>
            </table>
        </form>
        <div id="distDiv"></div>
        <table>
            <tr>
                <td class="show"><div id="clusterDiv"></div>
                <td class="show"><div id="assignmentDiv"></div>
        </table>
        <script type="text/javascript">

function analyze() {
    var eps = document.getElementsByName('epsilonInput')[0].value;
    var MinPts = document.getElementsByName('minPtsInput')[0].value;
    var D = readData();
    var dbscan = new DBSCAN(D, dist=egDist, eps=eps, MinPts=MinPts);
    showDist(dbscan);
    dbscan.run();
    showClusters(dbscan);
    showAssignments(dbscan);
    console.log('ok');
}

function egDist(p1, p2) {
    var dist = 0;
    for (var letter = 0; letter < 5; letter++)
        if (this.D[p1].charCodeAt(letter) != this.D[p2].charCodeAt(letter)) dist++;
    return dist;
}

function readData() {
    var dataInputs = document.getElementsByName('dataInput');
    var D = [];
    for (var i in dataInputs) {
        var value = dataInputs[i].value;
        if (value === 0 || value) {
            D.push(value);
        }
    }
    return D;
}

function showDist(dbscan) {
    var div = document.getElementById('distDiv');
    var existingTable = div.firstChild;
    if (existingTable) div.removeChild(existingTable);
    var table = document.createElement('table');
    var caption = document.createElement('caption');
    caption.innerHTML = "distance matrix";
    table.appendChild(caption);
    var n = dbscan.D.length;
    var row = new Array(n);
    for (var i = 0; i < n; i++) {
        row[i] = document.createElement('tr');
        var cell = new Array(n);
        for (var j = 0; j < n; j++) {
            cell[j] = document.createElement('td');
            cell[j].innerHTML = (i == j ? '\\' : dbscan.dist(i, j));
            row[i].appendChild(cell[j]);
        }
        table.appendChild(row[i]);
    }
    div.appendChild(table);
}

function showClusters(dbscan) {
    var div = document.getElementById('clusterDiv');
    var existingTable = div.firstChild;
    if (existingTable) div.removeChild(existingTable);
    var table = document.createElement('table');

    var headerRow = document.createElement('tr');
    var header = document.createElement('th');
    header.innerHTML = 'cluster';
    headerRow.appendChild(header);
    table.appendChild(headerRow);

    var nClusters = dbscan.cluster.length;
    var row = new Array(nClusters);
    for (var cluster = 0; cluster < nClusters; cluster++) {
        row[cluster] = document.createElement('tr');
        var clusterSize = dbscan.cluster[cluster].length;
        var cell = new Array(clusterSize);
        var clusterCell = document.createElement('th');
        clusterCell.innerHTML = cluster;
        row[cluster].appendChild(clusterCell);
        for (var p = 0; p < clusterSize; p++) {
            cell[p] = document.createElement('td');
            cell[p].innerHTML = dbscan.cluster[cluster][p];
            row[cluster].appendChild(cell[p]);
        }
        table.appendChild(row[cluster]);
    }
    div.appendChild(table);
}

function showAssignments(dbscan) {
    var div = document.getElementById('assignmentDiv');
    var existingTable = div.firstChild;
    if (existingTable) div.removeChild(existingTable);
    var table = document.createElement('table');
    var caption = document.createElement('caption');
    caption.innerHTML = 'assignments';
    table.appendChild(caption);

    var headerRow = document.createElement('tr');
    var col0 = document.createElement('th');
    col0.innerHTML = 'point';
    headerRow.appendChild(col0);
    var col1 = document.createElement('th');
    col1.innerHTML = 'cluster';
    headerRow.appendChild(col1);
    table.appendChild(headerRow);

    var n = dbscan.assigned.length;
    var row = new Array(n);
    for (var point = 0; point < n; point++) {
        row[point] = document.createElement('tr');
        var pointCell = document.createElement('td');
        pointCell.innerHTML = point;
        row[point].appendChild(pointCell);
        var clusterCell = document.createElement('td');
        clusterCell.innerHTML = dbscan.assigned[point] == -1 ? 'noise' : dbscan.assigned[point];
        row[point].appendChild(clusterCell);
        table.appendChild(row[point]);
    }
    div.appendChild(table);
}

        </script>
    </body>
</html>
